home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / Mesa-3.0 / SRC / VBXFORM.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-24  |  47.7 KB  |  1,452 lines

  1. /* $Id: vbxform.c,v 3.10 1998/08/23 22:19:30 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.0
  6.  * Copyright (C) 1995-1998  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: vbxform.c,v $
  26.  * Revision 3.10  1998/08/23 22:19:30  brianp
  27.  * added DoViewportMapping to context struct
  28.  *
  29.  * Revision 3.9  1998/07/09 03:15:41  brianp
  30.  * include asm_386.h instead of asm-386.h
  31.  *
  32.  * Revision 3.8  1998/06/22 03:16:28  brianp
  33.  * added MITS code
  34.  *
  35.  * Revision 3.7  1998/06/07 22:18:52  brianp
  36.  * implemented GL_EXT_multitexture extension
  37.  *
  38.  * Revision 3.6  1998/04/18 05:01:18  brianp
  39.  * renamed USE_ASM to USE_X86_ASM
  40.  *
  41.  * Revision 3.5  1998/03/28 04:01:53  brianp
  42.  * added CONST macro to fix IRIX compilation problems
  43.  *
  44.  * Revision 3.4  1998/03/27 04:26:44  brianp
  45.  * fixed G++ warnings
  46.  *
  47.  * Revision 3.3  1998/02/20 04:53:07  brianp
  48.  * implemented GL_SGIS_multitexture
  49.  *
  50.  * Revision 3.2  1998/02/02 03:09:34  brianp
  51.  * added GL_LIGHT_MODEL_COLOR_CONTROL (separate specular color interpolation)
  52.  *
  53.  * Revision 3.1  1998/02/01 16:37:19  brianp
  54.  * added GL_EXT_rescale_normal extension
  55.  *
  56.  * Revision 3.0  1998/01/31 21:06:45  brianp
  57.  * initial rev
  58.  *
  59.  */
  60.  
  61.  
  62. /*
  63.  * This file implements transformation, clip testing and projection of
  64.  * vertices in the vertex buffer.
  65.  *
  66.  * The entry points to this file are the functions:
  67.  *    gl_transform_vb_part1() - first stage of vertex transformation
  68.  *    gl_transform_vb_part2() - second stage of vertex transformation
  69.  */
  70.  
  71.  
  72. #ifdef PC_HEADER
  73. #include "all.h"
  74. #else
  75. #include <stdlib.h>
  76. #include "asm_386.h"
  77. #include "context.h"
  78. #include "fog.h"
  79. #include "light.h"
  80. #include "macros.h"
  81. #include "matrix.h"
  82. #include "mmath.h"
  83. #include "shade.h"
  84. #include "texture.h"
  85. #include "types.h"
  86. #include "vb.h"
  87. #include "vbrender.h"
  88. #include "vbxform.h"
  89. #include "xform.h"
  90. #endif
  91.  
  92.  
  93. #if 0  /* NOT USED AT THIS TIME */
  94. /*
  95.  * Use the current modelview matrix to transform XY vertices from object
  96.  * to eye coordinates.
  97.  * Input:  ctx - the context
  98.  *         n - number of vertices to transform
  99.  *         vObj - array [n][4] of object coordinates
  100.  * In/Out;  vEye - array [n][4] of eye coordinates
  101.  */
  102. static void transform_points2( GLcontext *ctx, GLuint n,
  103.                                const GLfloat vObj[][4], GLfloat vEye[][4] )
  104. {
  105.    switch (ctx->ModelViewMatrixType) {
  106.       case MATRIX_GENERAL:
  107.          {
  108.             const GLfloat *m = ctx->ModelViewMatrix;
  109.             GLfloat m0 = m[0],  m4 = m[4],  m12 = m[12];
  110.             GLfloat m1 = m[1],  m5 = m[5],  m13 = m[13];
  111.             GLfloat m2 = m[2],  m6 = m[6],  m14 = m[14];
  112.             GLfloat m3 = m[3],  m7 = m[7],  m15 = m[15];
  113.             GLuint i;
  114.             for (i=0;i<n;i++) {
  115.                GLfloat ox = vObj[i][0], oy = vObj[i][1];
  116.                vEye[i][0] = m0 * ox + m4 * oy + m12;
  117.                vEye[i][1] = m1 * ox + m5 * oy + m13;
  118.                vEye[i][2] = m2 * ox + m6 * oy + m14;
  119.                vEye[i][3] = m3 * ox + m7 * oy + m15;
  120.             }
  121.          }
  122.          break;
  123.       case MATRIX_IDENTITY:
  124.          {
  125.             GLuint i;
  126.             for (i=0;i<n;i++) {
  127.                vEye[i][0] = vObj[i][0];
  128.                vEye[i][1] = vObj[i][1];
  129.                vEye[i][2] = 0.0F;
  130.                vEye[i][3] = 1.0F;
  131.             }
  132.          }
  133.          break;
  134.       case MATRIX_2D:
  135.          {
  136.             const GLfloat *m = ctx->ModelViewMatrix;
  137.             GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
  138.             GLfloat m12 = m[12], m13 = m[13];
  139.             GLuint i;
  140.             for (i=0;i<n;i++) {
  141.                GLfloat ox = vObj[i][0], oy = vObj[i][1];
  142.                vEye[i][0] = m0 * ox + m4 * oy + m12;
  143.                vEye[i][1] = m1 * ox + m5 * oy + m13;
  144.                vEye[i][2] = 0.0F;
  145.                vEye[i][3] = 1.0F;
  146.             }
  147.          }
  148.          break;
  149.       case MATRIX_2D_NO_ROT:
  150.          {
  151.             const GLfloat *m = ctx->ModelViewMatrix;
  152.             GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13];
  153.             GLuint i;
  154.             for (i=0;i<n;i++) {
  155.                GLfloat ox = vObj[i][0], oy = vObj[i][1];
  156.                vEye[i][0] = m0 * ox           + m12;
  157.                vEye[i][1] =           m5 * oy + m13;
  158.                vEye[i][2] = 0.0F;
  159.                vEye[i][3] = 1.0F;
  160.             }
  161.          }
  162.          break;
  163.       case MATRIX_3D:
  164.          {
  165.             const GLfloat *m = ctx->ModelViewMatrix;
  166.             GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5];
  167.             GLfloat m6 = m[6], m12 = m[12], m13 = m[13], m14 = m[14];
  168.             GLuint i;
  169.             for (i=0;i<n;i++) {
  170.                GLfloat ox = vObj[i][0], oy = vObj[i][1];
  171.                vEye[i][0] = m0 * ox + m4 * oy + m12;
  172.                vEye[i][1] = m1 * ox + m5 * oy + m13;
  173.                vEye[i][2] = m2 * ox + m6 * oy + m14;
  174.                vEye[i][3] = 1.0F;
  175.             }
  176.          }
  177.          break;
  178.       default:
  179.          /* should never get here */
  180.          gl_problem( NULL, "invalid matrix type in transform_points3()" );
  181.          return;
  182.    }
  183. }
  184. #endif
  185.  
  186.  
  187. /*
  188.  * Use the current modelview matrix to transform XYZ vertices from object
  189.  * to eye coordinates.
  190.  * Input:  ctx - the context
  191.  *         n - number of vertices to transform
  192.  *         vObj - array [n][4] of object coordinates
  193.  * In/Out;  vEye - array [n][4] of eye coordinates
  194.  */
  195. static void transform_points3( GLcontext *ctx, GLuint n,
  196.                                CONST GLfloat vObj[][4], GLfloat vEye[][4] )
  197. {
  198. #ifndef USE_X86_ASM
  199.    START_FAST_MATH;
  200.    switch (ctx->ModelViewMatrixType) {
  201.       case MATRIX_GENERAL:
  202.          {
  203.             const GLfloat *m = ctx->ModelViewMatrix;
  204.             GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8],  m12 = m[12];
  205.             GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9],  m13 = m[13];
  206.             GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10],  m14 = m[14];
  207.             GLfloat m3 = m[3],  m7 = m[7],  m11 = m[11],  m15 = m[15];
  208.             GLuint i;
  209.             for (i=0;i<n;i++) {
  210.                GLfloat ox = vObj[i][0], oy = vObj[i][1], oz = vObj[i][2];
  211.                vEye[i][0] = m0 * ox + m4 * oy + m8  * oz + m12;
  212.                vEye[i][1] = m1 * ox + m5 * oy + m9  * oz + m13;
  213.                vEye[i][2] = m2 * ox + m6 * oy + m10 * oz + m14;
  214.                vEye[i][3] = m3 * ox + m7 * oy + m11 * oz + m15;
  215.             }
  216.          }
  217.          break;
  218.       case MATRIX_IDENTITY:
  219.          {
  220.             GLuint i;
  221.             for (i=0;i<n;i++) {
  222.                vEye[i][0] = vObj[i][0];
  223.                vEye[i][1] = vObj[i][1];
  224.                vEye[i][2] = vObj[i][2];
  225.                vEye[i][3] = 1.0F;
  226.             }
  227.          }
  228.          break;
  229.       case MATRIX_2D:
  230.          {
  231.             const GLfloat *m = ctx->ModelViewMatrix;
  232.             GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
  233.             GLfloat m12 = m[12], m13 = m[13];
  234.             GLuint i;
  235.             for (i=0;i<n;i++) {
  236.                GLfloat ox = vObj[i][0], oy = vObj[i][1], oz = vObj[i][2];
  237.                vEye[i][0] = m0 * ox + m4 * oy            + m12       ;
  238.                vEye[i][1] = m1 * ox + m5 * oy            + m13       ;
  239.                vEye[i][2] =                   +       oz             ;
  240.                vEye[i][3] =                                      1.0F;
  241.             }
  242.          }
  243.          break;
  244.       case MATRIX_2D_NO_ROT:
  245.          {
  246.             const GLfloat *m = ctx->ModelViewMatrix;
  247.             GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13];
  248.             GLuint i;
  249.             for (i=0;i<n;i++) {
  250.                GLfloat ox = vObj[i][0], oy = vObj[i][1], oz = vObj[i][2];
  251.                vEye[i][0] = m0 * ox                      + m12       ;
  252.                vEye[i][1] =           m5 * oy            + m13       ;
  253.                vEye[i][2] =                   +       oz             ;
  254.                vEye[i][3] =                                      1.0F;
  255.             }
  256.          }
  257.          break;
  258.       case MATRIX_3D:
  259.          {
  260.             const GLfloat *m = ctx->ModelViewMatrix;
  261.             GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5];
  262.             GLfloat m6 = m[6], m8 = m[8], m9 = m[9], m10 = m[10];
  263.             GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
  264.             GLuint i;
  265.             for (i=0;i<n;i++) {
  266.                GLfloat ox = vObj[i][0], oy = vObj[i][1], oz = vObj[i][2];
  267.                vEye[i][0] = m0 * ox + m4 * oy +  m8 * oz + m12       ;
  268.                vEye[i][1] = m1 * ox + m5 * oy +  m9 * oz + m13       ;
  269.                vEye[i][2] = m2 * ox + m6 * oy + m10 * oz + m14       ;
  270.                vEye[i][3] =                                      1.0F;
  271.             }
  272.          }
  273.          break;
  274.       default:
  275.          /* should never get here */
  276.          gl_problem( NULL, "invalid matrix type in transform_points3()" );
  277.    }
  278.    END_FAST_MATH;
  279. #else
  280.    switch (ctx->ModelViewMatrixType) {
  281.       case MATRIX_GENERAL:
  282.          asm_transform_points3_general( n, vEye, ctx->ModelViewMatrix, vObj );
  283.          break;
  284.       case MATRIX_IDENTITY:
  285.          asm_transform_points3_identity( n, vEye, vObj );
  286.          break;
  287.       case MATRIX_2D:
  288.          asm_transform_points3_2d( n, vEye, ctx->ModelViewMatrix, vObj );
  289.          break;
  290.       case MATRIX_2D_NO_ROT:
  291.          asm_transform_points3_2d_no_rot( n, vEye, ctx->ModelViewMatrix,
  292.                                           vObj );
  293.          break;
  294.       case MATRIX_3D:
  295.          asm_transform_points3_3d( n, vEye, ctx->ModelViewMatrix, vObj );
  296.          break;
  297.       default:
  298.          /* should never get here */
  299.          gl_problem( NULL, "invalid matrix type in transform_points3()" );
  300.          return;
  301.    }
  302. #endif
  303. }
  304.  
  305.  
  306.  
  307. /*
  308.  * Use the current modelview matrix to transform XYZW vertices from object
  309.  * to eye coordinates.
  310.  * Input:  ctx - the context
  311.  *         n - number of vertices to transform
  312.  *         vObj - array [n][4] of object coordinates
  313.  * In/Out;  vEye - array [n][4] of eye coordinates
  314.  */
  315. static void transform_points4( GLcontext *ctx, GLuint n,
  316.                                CONST GLfloat vObj[][4], GLfloat vEye[][4] )
  317. {
  318. #ifndef USE_X86_ASM
  319.    START_FAST_MATH;
  320.    switch (ctx->ModelViewMatrixType) {
  321.       case MATRIX_GENERAL:
  322.          {
  323.             const GLfloat *m = ctx->ModelViewMatrix;
  324.             GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8],  m12 = m[12];
  325.             GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9],  m13 = m[13];
  326.             GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10],  m14 = m[14];
  327.             GLfloat m3 = m[3],  m7 = m[7],  m11 = m[11],  m15 = m[15];
  328.             GLuint i;
  329.             for (i=0;i<n;i++) {
  330.                GLfloat ox = vObj[i][0], oy = vObj[i][1];
  331.                GLfloat oz = vObj[i][2], ow = vObj[i][3];
  332.                vEye[i][0] = m0 * ox + m4 * oy + m8  * oz + m12 * ow;
  333.                vEye[i][1] = m1 * ox + m5 * oy + m9  * oz + m13 * ow;
  334.                vEye[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 * ow;
  335.                vEye[i][3] = m3 * ox + m7 * oy + m11 * oz + m15 * ow;
  336.             }
  337.          }
  338.          break;
  339.       case MATRIX_IDENTITY:
  340.          {
  341.             GLuint i;
  342.             for (i=0;i<n;i++) {
  343.                vEye[i][0] = vObj[i][0];
  344.                vEye[i][1] = vObj[i][1];
  345.                vEye[i][2] = vObj[i][2];
  346.                vEye[i][3] = vObj[i][3];
  347.             }
  348.          }
  349.          break;
  350.       case MATRIX_2D:
  351.          {
  352.             const GLfloat *m = ctx->ModelViewMatrix;
  353.             GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
  354.             GLfloat m12 = m[12], m13 = m[13];
  355.             GLuint i;
  356.             for (i=0;i<n;i++) {
  357.                GLfloat ox = vObj[i][0], oy = vObj[i][1];
  358.                GLfloat oz = vObj[i][2], ow = vObj[i][3];
  359.                vEye[i][0] = m0 * ox + m4 * oy            + m12 * ow;
  360.                vEye[i][1] = m1 * ox + m5 * oy            + m13 * ow;
  361.                vEye[i][2] =                   +       oz           ;
  362.                vEye[i][3] =                                      ow;
  363.             }
  364.          }
  365.          break;
  366.       case MATRIX_2D_NO_ROT:
  367.          {
  368.             const GLfloat *m = ctx->ModelViewMatrix;
  369.             GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13];
  370.             GLuint i;
  371.             for (i=0;i<n;i++) {
  372.                GLfloat ox = vObj[i][0], oy = vObj[i][1];
  373.                GLfloat oz = vObj[i][2], ow = vObj[i][3];
  374.                vEye[i][0] = m0 * ox                      + m12 * ow;
  375.                vEye[i][1] =           m5 * oy            + m13 * ow;
  376.                vEye[i][2] =                   +       oz           ;
  377.                vEye[i][3] =                                      ow;
  378.             }
  379.          }
  380.          break;
  381.       case MATRIX_3D:
  382.          {
  383.             const GLfloat *m = ctx->ModelViewMatrix;
  384.             GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5];
  385.             GLfloat m6 = m[6], m8 = m[8], m9 = m[9], m10 = m[10];
  386.             GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
  387.             GLuint i;
  388.             for (i=0;i<n;i++) {
  389.                GLfloat ox = vObj[i][0], oy = vObj[i][1];
  390.                GLfloat oz = vObj[i][2], ow = vObj[i][3];
  391.                vEye[i][0] = m0 * ox + m4 * oy +  m8 * oz + m12 * ow;
  392.                vEye[i][1] = m1 * ox + m5 * oy +  m9 * oz + m13 * ow;
  393.                vEye[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 * ow;
  394.                vEye[i][3] =                                      ow;
  395.             }
  396.          }
  397.          break;
  398.       default:
  399.          /* should never get here */
  400.          gl_problem( NULL, "invalid matrix type in transform_points4()" );
  401.    }
  402.    END_FAST_MATH;
  403. #else
  404.    switch (ctx->ModelViewMatrixType) {
  405.       case MATRIX_GENERAL:
  406.          asm_transform_points4_general( n, vEye, ctx->ModelViewMatrix, vObj );
  407.          break;
  408.       case MATRIX_IDENTITY:
  409.          asm_transform_points4_identity( n, vEye, vObj );
  410.          break;
  411.       case MATRIX_2D:
  412.          asm_transform_points4_2d( n, vEye, ctx->ModelViewMatrix, vObj );
  413.          break;
  414.       case MATRIX_2D_NO_ROT:
  415.          asm_transform_points4_2d_no_rot( n, vEye, ctx->ModelViewMatrix,
  416.                                           vObj );
  417.          break;
  418.       case MATRIX_3D:
  419.          asm_transform_points4_3d( n, vEye, ctx->ModelViewMatrix, vObj );
  420.          break;
  421.       default:
  422.          /* should never get here */
  423.          gl_problem( NULL, "invalid matrix type in transform_points4()" );
  424.          return;
  425.    }
  426. #endif
  427. }
  428.  
  429.  
  430.  
  431. /*
  432.  * Transform an array of texture coordinates by the current texture matrix.
  433.  * Input:  ctx - the context
  434.  *         n - number of texture coordinates in array
  435.  *         texSet - which texture matrix to use
  436.  * In/Out:  t - array [n][4] of texture coordinates to transform
  437.  */
  438. static void transform_texcoords( GLcontext *ctx, GLuint n, GLfloat t[][4],
  439.                                  GLuint texSet )
  440. {
  441. #ifndef USE_X86_ASM
  442.    START_FAST_MATH;
  443.    switch (ctx->TextureMatrixType[texSet]) {
  444.       case MATRIX_GENERAL:
  445.          {
  446.             const GLfloat *m = ctx->TextureMatrix[texSet];
  447.             GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8],  m12 = m[12];
  448.             GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9],  m13 = m[13];
  449.             GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10],  m14 = m[14];
  450.             GLfloat m3 = m[3],  m7 = m[7],  m11 = m[11],  m15 = m[15];
  451.             GLuint i;
  452.             for (i=0;i<n;i++) {
  453.                GLfloat t0 = t[i][0], t1 = t[i][1], t2 = t[i][2], t3 = t[i][3];
  454.                t[i][0] = m0 * t0 + m4 * t1 + m8  * t2 + m12 * t3;
  455.                t[i][1] = m1 * t0 + m5 * t1 + m9  * t2 + m13 * t3;
  456.                t[i][2] = m2 * t0 + m6 * t1 + m10 * t2 + m14 * t3;
  457.                t[i][3] = m3 * t0 + m7 * t1 + m11 * t2 + m15 * t3;
  458.             }
  459.          }
  460.          break;
  461.       case MATRIX_IDENTITY:
  462.          /* Do nothing */
  463.          break;
  464.       case MATRIX_2D:
  465.          {
  466.             const GLfloat *m = ctx->TextureMatrix[texSet];
  467.             GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
  468.             GLfloat m12 = m[12], m13 = m[13];
  469.             GLuint i;
  470.             for (i=0;i<n;i++) {
  471.                GLfloat t0 = t[i][0], t1 = t[i][1], t2 = t[i][2], t3 = t[i][3];
  472.                t[i][0] = m0 * t0 + m4 * t1            + m12 * t3;
  473.                t[i][1] = m1 * t0 + m5 * t1            + m13 * t3;
  474.                t[i][2] =                   +       t2           ;
  475.                /*t[i][3] unchanged*/
  476.             }
  477.          }
  478.          break;
  479.       case MATRIX_3D:
  480.          {
  481.             const GLfloat *m = ctx->TextureMatrix[texSet];
  482.             GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5];
  483.             GLfloat m6 = m[6], m8 = m[8], m9 = m[9], m10 = m[10];
  484.             GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
  485.             GLuint i;
  486.             for (i=0;i<n;i++) {
  487.                GLfloat t0 = t[i][0], t1 = t[i][1], t2 = t[i][2], t3 = t[i][3];
  488.                t[i][0] = m0 * t0 + m4 * t1 +  m8 * t2 + m12 * t3;
  489.                t[i][1] = m1 * t0 + m5 * t1 +  m9 * t2 + m13 * t3;
  490.                t[i][2] = m2 * t0 + m6 * t1 + m10 * t2 + m14 * t3;
  491.                /*t[i][3] unchanged*/
  492.             }
  493.          }
  494.          break;
  495.       default:
  496.          /* should never get here */
  497.          gl_problem( NULL, "invalid matrix type in transform_texcoords()" );
  498.    }
  499.    END_FAST_MATH;
  500. #else
  501.    switch (ctx->TextureMatrixType[texSet]) {
  502.       case MATRIX_GENERAL:
  503.          asm_transform_points4_general( n, t, ctx->TextureMatrix[texSet], t );
  504.          break;
  505.       case MATRIX_IDENTITY:
  506.          /* Do nothing */
  507.          break;
  508.       case MATRIX_2D:
  509.          asm_transform_points4_2d( n, t, ctx->TextureMatrix[texSet], t );
  510.          break;
  511.       case MATRIX_3D:
  512.          asm_transform_points4_3d( n, t, ctx->TextureMatrix[texSet], t );
  513.          break;
  514.       default:
  515.          /* should never get here */
  516.          gl_problem( NULL, "invalid matrix type in transform_texcoords()" );
  517.          return;
  518.    }
  519. #endif
  520. }
  521.  
  522.  
  523.  
  524. /*
  525.  * Apply the projection matrix to an array of vertices in Eye coordinates
  526.  * resulting in Clip coordinates.  Also, compute the ClipMask bitfield for
  527.  * each vertex.
  528.  *
  529.  * NOTE: the volatile keyword is used in this function to ensure that the
  530.  * FP computations are computed to low-precision.  If high precision is
  531.  * used (ala 80-bit X86 arithmetic) then the clipMask results may be
  532.  * inconsistant with the computations in clip.c.  Later, clipped polygons
  533.  * may be rendered incorrectly.
  534.  *
  535.  * Input:  ctx - the context
  536.  *         n - number of vertices
  537.  *         vEye - array [n][4] of Eye coordinates
  538.  * Output:  vClip - array [n][4] of Clip coordinates
  539.  *          clipMask - array [n] of clip masks
  540.  */
  541. static void project_and_cliptest( GLcontext *ctx,
  542.                                   GLuint n, CONST GLfloat vEye[][4],
  543.                                   GLfloat vClip[][4], GLubyte clipMask[],
  544.                                   GLubyte *orMask, GLubyte *andMask )
  545.  
  546. {
  547. #ifndef USE_X86_ASM
  548.    GLubyte tmpOrMask = *orMask;
  549.    GLubyte tmpAndMask = *andMask;
  550.  
  551.    START_FAST_MATH;
  552.  
  553.    switch (ctx->ProjectionMatrixType) {
  554.       case MATRIX_GENERAL:
  555.          {
  556.             const GLfloat *m = ctx->ProjectionMatrix;
  557.             GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8],  m12 = m[12];
  558.             GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9],  m13 = m[13];
  559.             GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10],  m14 = m[14];
  560.             GLfloat m3 = m[3],  m7 = m[7],  m11 = m[11],  m15 = m[15];
  561.             GLuint i;
  562.             for (i=0;i<n;i++) {
  563.                GLfloat ex = vEye[i][0], ey = vEye[i][1];
  564.                GLfloat ez = vEye[i][2], ew = vEye[i][3];
  565.                GLfloat cx = m0 * ex + m4 * ey + m8  * ez + m12 * ew;
  566.                GLfloat cy = m1 * ex + m5 * ey + m9  * ez + m13 * ew;
  567.                GLfloat cz = m2 * ex + m6 * ey + m10 * ez + m14 * ew;
  568.                GLfloat cw = m3 * ex + m7 * ey + m11 * ez + m15 * ew;
  569.                GLubyte mask = 0;
  570.                vClip[i][0] = cx;
  571.                vClip[i][1] = cy;
  572.                vClip[i][2] = cz;
  573.                vClip[i][3] = cw;
  574.                if (cx >  cw)       mask |= CLIP_RIGHT_BIT;
  575.                else if (cx < -cw)  mask |= CLIP_LEFT_BIT;
  576.                if (cy >  cw)       mask |= CLIP_TOP_BIT;
  577.                else if (cy < -cw)  mask |= CLIP_BOTTOM_BIT;
  578.                if (cz >  cw)       mask |= CLIP_FAR_BIT;
  579.                else if (cz < -cw)  mask |= CLIP_NEAR_BIT;
  580.                if (mask) {
  581.                   clipMask[i] |= mask;
  582.                   tmpOrMask |= mask;
  583.                }
  584.                tmpAndMask &= mask;
  585.             }
  586.          }
  587.          break;
  588.       case MATRIX_IDENTITY:
  589.          {
  590.             GLuint i;
  591.             for (i=0;i<n;i++) {
  592.                GLfloat cx = vClip[i][0] = vEye[i][0];
  593.                GLfloat cy = vClip[i][1] = vEye[i][1];
  594.                GLfloat cz = vClip[i][2] = vEye[i][2];
  595.                GLfloat cw = vClip[i][3] = vEye[i][3];
  596.                GLubyte mask = 0;
  597.                if (cx >  cw)       mask |= CLIP_RIGHT_BIT;
  598.                else if (cx < -cw)  mask |= CLIP_LEFT_BIT;
  599.                if (cy >  cw)       mask |= CLIP_TOP_BIT;
  600.                else if (cy < -cw)  mask |= CLIP_BOTTOM_BIT;
  601.                if (cz >  cw)       mask |= CLIP_FAR_BIT;
  602.                else if (cz < -cw)  mask |= CLIP_NEAR_BIT;
  603.                if (mask) {
  604.                   clipMask[i] |= mask;
  605.                   tmpOrMask |= mask;
  606.                }
  607.                tmpAndMask &= mask;
  608.             }
  609.          }
  610.          break;
  611.       case MATRIX_ORTHO:
  612.          {
  613.             const GLfloat *m = ctx->ProjectionMatrix;
  614.             GLfloat m0 = m[0], m5 = m[5], m10 = m[10], m12 = m[12];
  615.             GLfloat m13 = m[13], m14 = m[14];
  616.             GLuint i;
  617.             for (i=0;i<n;i++) {
  618.                GLfloat ex = vEye[i][0], ey = vEye[i][1];
  619.                GLfloat ez = vEye[i][2], ew = vEye[i][3];
  620.                volatile GLfloat cx = m0 * ex                      + m12 * ew;
  621.                volatile GLfloat cy =           m5 * ey            + m13 * ew;
  622.                volatile GLfloat cz =                     m10 * ez + m14 * ew;
  623.                volatile GLfloat cw =                                      ew;
  624.                GLubyte mask = 0;
  625.                vClip[i][0] = cx;
  626.                vClip[i][1] = cy;
  627.                vClip[i][2] = cz;
  628.                vClip[i][3] = cw;
  629.                if (cx >  cw)       mask |= CLIP_RIGHT_BIT;
  630.                else if (cx < -cw)  mask |= CLIP_LEFT_BIT;
  631.                if (cy >  cw)       mask |= CLIP_TOP_BIT;
  632.                else if (cy < -cw)  mask |= CLIP_BOTTOM_BIT;
  633.                if (cz >  cw)       mask |= CLIP_FAR_BIT;
  634.                else if (cz < -cw)  mask |= CLIP_NEAR_BIT;
  635.                if (mask) {
  636.                   clipMask[i] |= mask;
  637.                   tmpOrMask |= mask;
  638.                }
  639.                tmpAndMask &= mask;
  640.             }
  641.          }
  642.          break;
  643.       case MATRIX_PERSPECTIVE:
  644.          {
  645.             const GLfloat *m = ctx->ProjectionMatrix;
  646.             GLfloat m0 = m[0], m5 = m[5], m8 = m[8], m9 = m[9];
  647.             GLfloat m10 = m[10], m14 = m[14];
  648.             GLuint i;
  649.             for (i=0;i<n;i++) {
  650.                GLfloat ex = vEye[i][0], ey = vEye[i][1];
  651.                GLfloat ez = vEye[i][2], ew = vEye[i][3];
  652.                volatile GLfloat cx = m0 * ex           + m8  * ez           ;
  653.                volatile GLfloat cy =           m5 * ey + m9  * ez           ;
  654.                volatile GLfloat cz =                     m10 * ez + m14 * ew;
  655.                volatile GLfloat cw =                          -ez           ;
  656.                GLubyte mask = 0;
  657.                vClip[i][0] = cx;
  658.                vClip[i][1] = cy;
  659.                vClip[i][2] = cz;
  660.                vClip[i][3] = cw;
  661.                if (cx >  cw)       mask |= CLIP_RIGHT_BIT;
  662.                else if (cx < -cw)  mask |= CLIP_LEFT_BIT;
  663.                if (cy >  cw)       mask |= CLIP_TOP_BIT;
  664.                else if (cy < -cw)  mask |= CLIP_BOTTOM_BIT;
  665.                if (cz >  cw)       mask |= CLIP_FAR_BIT;
  666.                else if (cz < -cw)  mask |= CLIP_NEAR_BIT;
  667.                if (mask) {
  668.                   clipMask[i] |= mask;
  669.                   tmpOrMask |= mask;
  670.                }
  671.                tmpAndMask &= mask;
  672.             }
  673.          }
  674.          break;
  675.       default:
  676.          /* should never get here */
  677.          gl_problem( NULL, "invalid matrix type in project_and_cliptest()" );
  678.    }
  679.  
  680.    *orMask = tmpOrMask;
  681.    *andMask = tmpAndMask;
  682.    END_FAST_MATH;
  683. #else
  684.    switch (ctx->ProjectionMatrixType) {
  685.       case MATRIX_GENERAL:
  686.          asm_project_and_cliptest_general( n, vClip, ctx->ProjectionMatrix, vEye, 
  687.                                            clipMask, orMask, andMask );
  688.          break;
  689.       case MATRIX_IDENTITY:
  690.          asm_project_and_cliptest_identity( n, vClip, vEye, clipMask, orMask, andMask );
  691.          break;
  692.       case MATRIX_ORTHO:
  693.          asm_project_and_cliptest_ortho( n, vClip, ctx->ProjectionMatrix, vEye, 
  694.                                          clipMask, orMask, andMask );
  695.          break;
  696.       case MATRIX_PERSPECTIVE:
  697.          asm_project_and_cliptest_perspective( n, vClip, ctx->ProjectionMatrix,
  698.                                                vEye, clipMask, orMask, andMask );
  699.          break;
  700.       default:
  701.          /* should never get here */
  702.          gl_problem( NULL, "invalid matrix type in project_and_cliptest()" );
  703.          return;
  704.    }
  705. #endif
  706. }
  707.  
  708.  
  709. /* This value matches the one in clip.c, used to cope with numeric error. */
  710. #define MAGIC_NUMBER -0.8e-03F
  711.  
  712. /*
  713.  * Test an array of vertices against the user-defined clipping planes.
  714.  * Input:  ctx - the context
  715.  *         n - number of vertices
  716.  *         vEye - array [n] of vertices, in eye coordinate system
  717.  * Output:  clipMask - array [n] of clip values: 0=not clipped, !0=clipped
  718.  * Return:  CLIP_ALL - if all vertices are clipped by one of the planes
  719.  *          CLIP_NONE - if no vertices were clipped
  720.  *          CLIP_SOME - if some vertices were clipped
  721.  */
  722. static GLuint userclip_vertices( GLcontext *ctx, GLuint n,
  723.                                  CONST GLfloat vEye[][4],
  724.                                  GLubyte clipMask[] )
  725. {
  726.    GLboolean anyClipped = GL_FALSE;
  727.    GLuint p;
  728.  
  729.    ASSERT(ctx->Transform.AnyClip);
  730.  
  731.    START_FAST_MATH;
  732.  
  733.    for (p=0;p<MAX_CLIP_PLANES;p++) {
  734.       if (ctx->Transform.ClipEnabled[p]) {
  735.          GLfloat a = ctx->Transform.ClipEquation[p][0];
  736.          GLfloat b = ctx->Transform.ClipEquation[p][1];
  737.          GLfloat c = ctx->Transform.ClipEquation[p][2];
  738.          GLfloat d = ctx->Transform.ClipEquation[p][3];
  739.          GLboolean allClipped = GL_TRUE;
  740.          GLuint i;
  741.          for (i=0;i<n;i++) {
  742.             GLfloat dot = vEye[i][0] * a + vEye[i][1] * b
  743.                         + vEye[i][2] * c + vEye[i][3] * d;
  744.             if (dot < MAGIC_NUMBER) {
  745.                /* this vertex is clipped */
  746.                clipMask[i] = CLIP_USER_BIT;
  747.                anyClipped = GL_TRUE;
  748.             }
  749.             else {
  750.                /* vertex not clipped */
  751.                allClipped = GL_FALSE;
  752.             }
  753.          }
  754.          if (allClipped) {
  755.             return CLIP_ALL;
  756.          }
  757.       }
  758.    }
  759.  
  760.    END_FAST_MATH;
  761.  
  762.    return anyClipped ? CLIP_SOME : CLIP_NONE;
  763. }
  764.  
  765.  
  766. /*
  767.  * Transform an array of vertices from clip coordinate space to window
  768.  * coordinates.
  769.  * Input:  ctx - the context
  770.  *         n - number of vertices to transform
  771.  *         vClip - array [n] of input vertices
  772.  *         clipMask - array [n] of vertex clip masks.  NULL = no clipped verts
  773.  * Output:  vWin - array [n] of vertices in window coordinate system
  774.  */
  775. static void viewport_map_vertices( GLcontext *ctx,
  776.                                    GLuint n, CONST GLfloat vClip[][4],
  777.                                    const GLubyte clipMask[], GLfloat vWin[][3])
  778. {
  779.  
  780.    GLfloat sx = ctx->Viewport.Sx;
  781.    GLfloat tx = ctx->Viewport.Tx;
  782.    GLfloat sy = ctx->Viewport.Sy;
  783.    GLfloat ty = ctx->Viewport.Ty;
  784.    GLfloat sz = ctx->Viewport.Sz;
  785.    GLfloat tz = ctx->Viewport.Tz;
  786.  
  787.  
  788.    START_FAST_MATH;
  789.  
  790.    if ((ctx->ProjectionMatrixType==MATRIX_ORTHO || 
  791.         ctx->ProjectionMatrixType==MATRIX_IDENTITY)
  792.        && ctx->ModelViewMatrixType!=MATRIX_GENERAL
  793.        && (ctx->VB->VertexSizeMask & VERTEX4_BIT)==0) {
  794.       /* don't need to divide by W */
  795.       if (clipMask) {
  796.          /* one or more vertices are clipped */
  797.          GLuint i;
  798.          for (i=0;i<n;i++) {
  799.             if (clipMask[i]==0) {
  800.                vWin[i][0] = vClip[i][0] * sx + tx;
  801.                vWin[i][1] = vClip[i][1] * sy + ty;
  802.                vWin[i][2] = vClip[i][2] * sz + tz;
  803.             }
  804.          }
  805.       }
  806.       else {
  807.          /* no vertices are clipped */
  808.          GLuint i;
  809.          for (i=0;i<n;i++) {
  810.             vWin[i][0] = vClip[i][0] * sx + tx;
  811.             vWin[i][1] = vClip[i][1] * sy + ty;
  812.             vWin[i][2] = vClip[i][2] * sz + tz;
  813.          }
  814.       }
  815.    }
  816.    else {
  817.       /* need to divide by W */
  818.       if (clipMask) {
  819.          /* one or more vertices are clipped */
  820.          GLuint i;
  821.          for (i=0;i<n;i++) {
  822.             if (clipMask[i] == 0) {
  823.                if (vClip[i][3] != 0.0F) {
  824.                   GLfloat wInv = 1.0F / vClip[i][3];
  825.                   vWin[i][0] = vClip[i][0] * wInv * sx + tx;
  826.                   vWin[i][1] = vClip[i][1] * wInv * sy + ty;
  827.                   vWin[i][2] = vClip[i][2] * wInv * sz + tz;
  828.                }
  829.                else {
  830.                   /* Div by zero!  Can't set window coords to infinity, so...*/
  831.                   vWin[i][0] = 0.0F;
  832.                   vWin[i][1] = 0.0F;
  833.                   vWin[i][2] = 0.0F;
  834.                }
  835.             }
  836.          }
  837.       }
  838.       else {
  839.          /* no vertices are clipped */
  840.          GLuint i;
  841.          for (i=0;i<n;i++) {
  842.             if (vClip[i][3] != 0.0F) {
  843.                GLfloat wInv = 1.0F / vClip[i][3];
  844.                vWin[i][0] = vClip[i][0] * wInv * sx + tx;
  845.                vWin[i][1] = vClip[i][1] * wInv * sy + ty;
  846.                vWin[i][2] = vClip[i][2] * wInv * sz + tz;
  847.             }
  848.             else {
  849.                /* Divide by zero!  Can't set window coords to infinity, so...*/
  850.                vWin[i][0] = 0.0F;
  851.                vWin[i][1] = 0.0F;
  852.                vWin[i][2] = 0.0F;
  853.             }
  854.          }
  855.       }
  856.    }
  857.  
  858.    END_FAST_MATH;
  859. }
  860.  
  861.  
  862.  
  863. /*
  864.  * Check if the global material has to be updated with info that was
  865.  * associated with a vertex via glMaterial.
  866.  * This function is used when any material values get changed between
  867.  * glBegin/glEnd either by calling glMaterial() or by calling glColor()
  868.  * when GL_COLOR_MATERIAL is enabled.
  869.  */
  870. static void update_material( GLcontext *ctx, GLuint i )
  871. {
  872.    struct vertex_buffer *VB = ctx->VB;
  873.  
  874.    if (VB->MaterialMask[i]) {
  875.       if (VB->MaterialMask[i] & FRONT_AMBIENT_BIT) {
  876.          COPY_4V( ctx->Light.Material[0].Ambient, VB->Material[i][0].Ambient );
  877.       }
  878.       if (VB->MaterialMask[i] & BACK_AMBIENT_BIT) {
  879.          COPY_4V( ctx->Light.Material[1].Ambient, VB->Material[i][1].Ambient );
  880.       }
  881.       if (VB->MaterialMask[i] & FRONT_DIFFUSE_BIT) {
  882.          COPY_4V( ctx->Light.Material[0].Diffuse, VB->Material[i][0].Diffuse );
  883.       }
  884.       if (VB->MaterialMask[i] & BACK_DIFFUSE_BIT) {
  885.          COPY_4V( ctx->Light.Material[1].Diffuse, VB->Material[i][1].Diffuse );
  886.       }
  887.       if (VB->MaterialMask[i] & FRONT_SPECULAR_BIT) {
  888.          COPY_4V( ctx->Light.Material[0].Specular, VB->Material[i][0].Specular );
  889.       }
  890.       if (VB->MaterialMask[i] & BACK_SPECULAR_BIT) {
  891.          COPY_4V( ctx->Light.Material[1].Specular, VB->Material[i][1].Specular );
  892.       }
  893.       if (VB->MaterialMask[i] & FRONT_EMISSION_BIT) {
  894.          COPY_4V( ctx->Light.Material[0].Emission, VB->Material[i][0].Emission );
  895.       }
  896.       if (VB->MaterialMask[i] & BACK_EMISSION_BIT) {
  897.          COPY_4V( ctx->Light.Material[1].Emission, VB->Material[i][1].Emission );
  898.       }
  899.       if (VB->MaterialMask[i] & FRONT_SHININESS_BIT) {
  900.          ctx->Light.Material[0].Shininess = VB->Material[i][0].Shininess;
  901.          gl_compute_material_shine_table( &ctx->Light.Material[0] );
  902.       }
  903.       if (VB->MaterialMask[i] & BACK_SHININESS_BIT) {
  904.          ctx->Light.Material[1].Shininess = VB->Material[i][1].Shininess;
  905.          gl_compute_material_shine_table( &ctx->Light.Material[1] );
  906.       }
  907.       if (VB->MaterialMask[i] & FRONT_INDEXES_BIT) {
  908.          ctx->Light.Material[0].AmbientIndex = VB->Material[i][0].AmbientIndex;
  909.          ctx->Light.Material[0].DiffuseIndex = VB->Material[i][0].DiffuseIndex;
  910.          ctx->Light.Material[0].SpecularIndex = VB->Material[i][0].SpecularIndex;
  911.       }
  912.       if (VB->MaterialMask[i] & BACK_INDEXES_BIT) {
  913.          ctx->Light.Material[1].AmbientIndex = VB->Material[i][1].AmbientIndex;
  914.          ctx->Light.Material[1].DiffuseIndex = VB->Material[i][1].DiffuseIndex;
  915.          ctx->Light.Material[1].SpecularIndex = VB->Material[i][1].SpecularIndex;
  916.       }
  917.       VB->MaterialMask[i] = 0;  /* reset now */
  918.    }
  919. }
  920.  
  921.  
  922. /*
  923.  * Compute the shading (lighting) for the vertices in the vertex buffer.
  924.  */
  925. static void shade_vertices( GLcontext *ctx, GLuint vbStart, GLuint vbCount )
  926. {
  927.    struct vertex_buffer *VB = ctx->VB;
  928.  
  929.    if (ctx->Visual->RGBAflag && ctx->Texture.Enabled
  930.        && ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR) {
  931.       /* Separate specular color */
  932.       if (!VB->MonoMaterial) {
  933.          /* Material may change with each vertex */
  934.          GLuint i;
  935.          for (i=vbStart; i<vbCount; i++) {
  936.             update_material( ctx, i );
  937.             gl_shade_rgba_spec( ctx, 0, 1, &VB->Eye[i],
  938.                                 &VB->Normal[i], &VB->Fcolor[i], &VB->Fspec[i]);
  939.             if (ctx->Light.Model.TwoSide) {
  940.                gl_shade_rgba_spec( ctx, 1, 1, &VB->Eye[i],
  941.                                  &VB->Normal[i], &VB->Bcolor[i], &VB->Bspec[i]);
  942.             }
  943.          }
  944.          /* Need this in case a glColor/glMaterial is called after the
  945.           * last vertex between glBegin/glEnd.
  946.           */
  947.          update_material( ctx, vbCount );
  948.       }
  949.       else {
  950.          /* call slower, full-featured shader */
  951.          gl_shade_rgba_spec( ctx, 0,
  952.                              vbCount - vbStart,
  953.                              VB->Eye + vbStart,
  954.                              VB->Normal + vbStart,
  955.                              VB->Fcolor + vbStart,
  956.                              VB->Fspec + vbStart );
  957.          if (ctx->Light.Model.TwoSide) {
  958.             gl_shade_rgba_spec( ctx, 1,
  959.                                 vbCount - vbStart,
  960.                                 VB->Eye + vbStart,
  961.                                 VB->Normal + vbStart,
  962.                                 VB->Bcolor + vbStart,
  963.                                 VB->Bspec + vbStart );
  964.          }
  965.       }
  966.    }
  967.    else if (ctx->Visual->RGBAflag) {
  968.       if (!VB->MonoMaterial) {
  969.          /* Material may change with each vertex */
  970.          GLuint i;
  971.          for (i=vbStart; i<vbCount; i++) {
  972.             update_material( ctx, i );
  973.             gl_shade_rgba( ctx, 0, 1, &VB->Eye[i],
  974.                            &VB->Normal[i], &VB->Fcolor[i]);
  975.             if (ctx->Light.Model.TwoSide) {
  976.                gl_shade_rgba( ctx, 1, 1, &VB->Eye[i],
  977.                               &VB->Normal[i], &VB->Bcolor[i]);
  978.             }
  979.          }
  980.          /* Need this in case a glColor/glMaterial is called after the
  981.           * last vertex between glBegin/glEnd.
  982.           */
  983.          update_material( ctx, vbCount );
  984.       }
  985.       else {
  986.          if (ctx->Light.Fast) {
  987.             if (VB->MonoNormal) {
  988.                /* call optimized shader */
  989.                GLubyte color[1][4];
  990.                GLuint i;
  991.                gl_shade_rgba_fast( ctx, 0,  /* front side */
  992.                                    1, VB->Normal + vbStart, color );
  993.                for (i=vbStart; i<vbCount; i++) {
  994.                   COPY_4V( VB->Fcolor[i], color[0] );
  995.                }
  996.                if (ctx->Light.Model.TwoSide) {
  997.                   gl_shade_rgba_fast( ctx, 1,  /* back side */
  998.                                       1, VB->Normal + vbStart, color );
  999.                   for (i=vbStart; i<vbCount; i++) {
  1000.                      COPY_4V( VB->Bcolor[i], color[0] );
  1001.                   }
  1002.                }
  1003.  
  1004.             }
  1005.             else {
  1006.                /* call optimized shader */
  1007.                gl_shade_rgba_fast( ctx, 0,  /* front side */
  1008.                                    vbCount - vbStart,
  1009.                                    VB->Normal + vbStart,
  1010.                                    VB->Fcolor + vbStart );
  1011.                if (ctx->Light.Model.TwoSide) {
  1012.                   gl_shade_rgba_fast( ctx, 1,  /* back side */
  1013.                                       vbCount - vbStart,
  1014.                                       VB->Normal + vbStart,
  1015.                                       VB->Bcolor + vbStart );
  1016.                }
  1017.             }
  1018.          }
  1019.          else {
  1020.             /* call slower, full-featured shader */
  1021.             gl_shade_rgba( ctx, 0,
  1022.                            vbCount - vbStart,
  1023.                            VB->Eye + vbStart,
  1024.                            VB->Normal + vbStart,
  1025.                            VB->Fcolor + vbStart );
  1026.             if (ctx->Light.Model.TwoSide) {
  1027.                gl_shade_rgba( ctx, 1,
  1028.                               vbCount - vbStart,
  1029.                               VB->Eye + vbStart,
  1030.                               VB->Normal + vbStart,
  1031.                               VB->Bcolor + vbStart );
  1032.             }
  1033.          }
  1034.       }
  1035.    }
  1036.    else {
  1037.       /* Color index mode */
  1038.       if (!VB->MonoMaterial) {
  1039.          /* Material may change with each vertex */
  1040.          GLuint i;
  1041.          /* NOTE the <= here.  This is needed in case glColor/glMaterial
  1042.           * is called after the last glVertex inside a glBegin/glEnd pair.
  1043.           */
  1044.          for (i=vbStart; i<vbCount; i++) {
  1045.             update_material( ctx, i );
  1046.             gl_shade_ci( ctx, 0, 1, &VB->Eye[i],
  1047.                          &VB->Normal[i], &VB->Findex[i] );
  1048.             if (ctx->Light.Model.TwoSide) {
  1049.                gl_shade_ci( ctx, 1, 1, &VB->Eye[i],
  1050.                             &VB->Normal[i], &VB->Bindex[i] );
  1051.             }
  1052.          }
  1053.          /* Need this in case a glColor/glMaterial is called after the
  1054.           * last vertex between glBegin/glEnd.
  1055.           */
  1056.          update_material( ctx, vbCount );
  1057.       }
  1058.       else {
  1059.          gl_shade_ci( ctx, 0,
  1060.                       vbCount - vbStart,
  1061.                       VB->Eye + vbStart,
  1062.                       VB->Normal + vbStart,
  1063.                       VB->Findex + vbStart );
  1064.          if (ctx->Light.Model.TwoSide) {
  1065.             gl_shade_ci( ctx, 1,
  1066.                          vbCount - vbStart,
  1067.                          VB->Eye + vbStart,
  1068.                          VB->Normal + vbStart,
  1069.                          VB->Bindex + vbStart );
  1070.          }
  1071.       }
  1072.    }
  1073. }
  1074.  
  1075.  
  1076.  
  1077. /*
  1078.  * Compute fog for the vertices in the vertex buffer.
  1079.  */
  1080. static void fog_vertices( GLcontext *ctx, GLuint vbStart, GLuint vbCount )
  1081. {
  1082.    struct vertex_buffer *VB = ctx->VB;
  1083.  
  1084.    if (ctx->Visual->RGBAflag) {
  1085.       /* Fog RGB colors */
  1086.       gl_fog_rgba_vertices( ctx, vbCount - vbStart,
  1087.                             VB->Eye + vbStart,
  1088.                             VB->Fcolor + vbStart );
  1089.       if (ctx->LightTwoSide) {
  1090.          gl_fog_rgba_vertices( ctx, vbCount - vbStart,
  1091.                                VB->Eye + vbStart,
  1092.                                VB->Bcolor + vbStart );
  1093.       }
  1094.    }
  1095.    else {
  1096.       /* Fog color indexes */
  1097.       gl_fog_ci_vertices( ctx, vbCount - vbStart,
  1098.                           VB->Eye + vbStart,
  1099.                           VB->Findex + vbStart );
  1100.       if (ctx->LightTwoSide) {
  1101.          gl_fog_ci_vertices( ctx, vbCount - vbStart,
  1102.                              VB->Eye + vbStart,
  1103.                              VB->Bindex + vbStart );
  1104.       }
  1105.    }
  1106. }
  1107.  
  1108.  
  1109. /*
  1110.  * Transform vertices, compute lighting, clipflags,
  1111.  * fog, texture coords, etc.
  1112.  *
  1113.  * Return the clipOrMask and clipAndMask values for the given VB range
  1114.  */
  1115. static void gl_transform_vb_range( GLcontext *ctx, GLuint vbStart, GLuint vbCount,
  1116.                    GLubyte *clipOrMask, GLubyte *clipAndMask,
  1117.                    GLboolean firstPartToDo)
  1118. {
  1119.   struct vertex_buffer *VB = ctx->VB;
  1120.  
  1121.   if (firstPartToDo) {
  1122.     /* Apply the modelview matrix to transform vertexes from Object
  1123.      * to Eye coords.
  1124.      */
  1125.     if (VB->VertexSizeMask==VERTEX4_BIT) {
  1126.       transform_points4( ctx, vbCount - vbStart,
  1127.              VB->Obj + vbStart, VB->Eye + vbStart );
  1128.     }
  1129.     else {
  1130.       transform_points3( ctx, vbCount - vbStart,
  1131.              VB->Obj + vbStart, VB->Eye + vbStart );
  1132.     }
  1133.  
  1134.     /* Now transform the normal vectors */
  1135.     if (ctx->NeedNormals) {
  1136.       gl_xform_normals_3fv( vbCount - vbStart,
  1137.                 VB->Normal + vbStart, ctx->ModelViewInv,
  1138.                 VB->Normal + vbStart, ctx->Transform.Normalize,
  1139.                 ctx->Transform.RescaleNormals );
  1140.     }
  1141.   }
  1142.  
  1143.   /* Test vertices in eye coordinate space against user clipping planes */
  1144.   if (ctx->Transform.AnyClip) {
  1145.     GLuint result = userclip_vertices( ctx, vbCount - vbStart,
  1146.                        VB->Eye + vbStart,
  1147.                        VB->ClipMask + vbStart );
  1148.     if (result==CLIP_ALL) {
  1149.       /* All vertices were outside one of the clip planes! */
  1150.       *clipOrMask = CLIP_ALL_BITS; /* force reset of clipping flags */
  1151.       *clipAndMask = CLIP_ALL_BITS;
  1152.       return;
  1153.     }
  1154.     else if (result==CLIP_SOME) {
  1155.       *clipOrMask = CLIP_USER_BIT;
  1156.     }
  1157.     else {
  1158.       *clipAndMask = 0;
  1159.     }
  1160.   }
  1161.  
  1162.   /* Apply the projection matrix to the Eye coordinates, resulting in
  1163.    * Clip coordinates.  Also, compute the ClipMask for each vertex.
  1164.    */
  1165.   project_and_cliptest( ctx, vbCount - vbStart, VB->Eye + vbStart,
  1166.             VB->Clip + vbStart, VB->ClipMask + vbStart,
  1167.             clipOrMask, clipAndMask );
  1168.  
  1169.   if (*clipAndMask) {
  1170.     /* All vertices clipped by one plane, all done! */
  1171.     *clipOrMask = CLIP_ALL_BITS; /* force reset of clipping flags */
  1172.     return;
  1173.   }
  1174.  
  1175.   /* Lighting */
  1176.   if (ctx->Light.Enabled) {
  1177.     shade_vertices(ctx, vbStart, vbCount);
  1178.   }
  1179.  
  1180.   /* Per-vertex fog */
  1181.   if (ctx->Fog.Enabled && ctx->Hint.Fog!=GL_NICEST) {
  1182.     fog_vertices(ctx, vbStart, vbCount);
  1183.   }
  1184.  
  1185.   /* Generate/transform texture coords */
  1186.   if (ctx->Texture.Enabled || ctx->RenderMode==GL_FEEDBACK) {
  1187.     GLuint texSet;
  1188.     for (texSet=0; texSet<MAX_TEX_COORD_SETS; texSet++) {
  1189.       if (ctx->Texture.Set[texSet].TexGenEnabled) {
  1190.     gl_texgen( ctx, vbCount - vbStart,
  1191.            VB->Obj + vbStart,
  1192.            VB->Eye + vbStart,
  1193.            VB->Normal + vbStart,
  1194.            VB->MultiTexCoord[texSet] + vbStart,
  1195.            texSet );
  1196.       }
  1197.     }
  1198.     for (texSet=0; texSet<MAX_TEX_COORD_SETS; texSet++) {
  1199.       if (ctx->TextureMatrixType[texSet] != MATRIX_IDENTITY) {
  1200.     transform_texcoords( ctx, vbCount - vbStart,
  1201.                  VB->MultiTexCoord[texSet] + vbStart,
  1202.                  texSet );
  1203.       }
  1204.     }
  1205.   }
  1206.   
  1207.   /* Use the viewport parameters to transform vertices from Clip
  1208.    * coordinates to Window coordinates.
  1209.    */
  1210.   if (ctx->DoViewportMapping) {
  1211.      viewport_map_vertices( ctx, vbCount - vbStart, VB->Clip + vbStart,
  1212.                      (*clipOrMask) ? VB->ClipMask + vbStart : (GLubyte*) NULL,
  1213.              VB->Win + vbStart );
  1214.   }
  1215.  
  1216.   /* Device driver rasterization setup.  3Dfx driver, for example. */
  1217.   if (ctx->Driver.RasterSetup) {
  1218.     (*ctx->Driver.RasterSetup)( ctx, vbStart, vbCount );
  1219.   }
  1220. }
  1221.  
  1222.  
  1223. #ifdef MITS
  1224.  
  1225. #include <pthread.h>
  1226. #include <semaphore.h>
  1227. #include <sys/time.h>
  1228. #include <sys/resource.h>
  1229. #include <sched.h>
  1230. #include <unistd.h>
  1231.  
  1232.  
  1233. /* Flag to indicate first time through */
  1234. static int firsttime=1;
  1235.  
  1236. /* Semaphores for the vertex buffer processing threads */
  1237. static sem_t tDone1, tDone2;
  1238.  
  1239. pthread_attr_t attr1, attr2;
  1240. pthread_t thread1, thread2;
  1241.  
  1242.  
  1243. typedef struct {
  1244.  
  1245.   GLuint start;
  1246.   GLuint count;
  1247.   GLcontext *ctx;
  1248.   GLboolean firstPartToDo;
  1249.   sem_t *thread_sem;
  1250.   volatile int tsync;
  1251.  
  1252. } GLtsched;
  1253.  
  1254.  
  1255. static  GLtsched set1, set2;
  1256.  
  1257.  
  1258. /* These are the processing threads for the vertex buffer */
  1259. void *gl_transform_vb_range_scheduler(void *s) 
  1260. {
  1261.   struct vertex_buffer *VB;
  1262.   GLtsched *set=(GLtsched *)s;
  1263.  
  1264.   int sval;
  1265.  
  1266.   while(1) {
  1267.  
  1268.     /* Sleep until main thread wakes us up again */
  1269.     sem_wait( set->thread_sem );
  1270.  
  1271.     VB = set->ctx->VB;
  1272.  
  1273.     gl_transform_vb_range( set->ctx, set->start, set->count,
  1274.                            &VB->ClipOrMask, &VB->ClipAndMask,
  1275.                            set->firstPartToDo );
  1276.     set->tsync = 1;
  1277.  
  1278.   } /* end while */
  1279.  
  1280.   return NULL;
  1281.  
  1282. } /* end gl_transform_vb_range_scheduler */
  1283. #endif
  1284.  
  1285.  
  1286. void gl_transform_vb( GLcontext *ctx, GLboolean firstPartToDo, GLboolean allDone )
  1287. {
  1288.   struct vertex_buffer *VB = ctx->VB;
  1289. #ifdef MITS
  1290.   struct sched_param sparam1, sparam2, mparams;
  1291. #endif
  1292.  
  1293. #ifdef PROFILE
  1294.   GLdouble t0 = gl_time();
  1295. #endif
  1296.  
  1297.   ASSERT( VB->Count>0 );
  1298.  
  1299. #ifdef PROFILE
  1300.   ctx->VertexTime += gl_time() - t0;
  1301.   ctx->VertexCount += VB->Count - VB->Start;
  1302. #endif
  1303.   
  1304.   if ((ctx->Texture.Enabled || ctx->RenderMode==GL_FEEDBACK) &&
  1305.       ctx->NewTextureMatrix)
  1306.     gl_analyze_texture_matrix(ctx);
  1307.  
  1308.   if (ctx->Driver.RasterSetup && VB->Start) {
  1309.       (*ctx->Driver.RasterSetup)( ctx, 0, VB->Start );
  1310.   }
  1311.  
  1312. #ifdef MITS
  1313.  
  1314.   if (VB->Count > 72) {
  1315.  
  1316.     if( firsttime ) {
  1317.  
  1318.       int policy;
  1319.      
  1320.  
  1321.       if( !getuid() ) {
  1322.     policy = SCHED_FIFO;
  1323.       }
  1324.       else {
  1325.     policy = SCHED_OTHER;
  1326.       }
  1327.  
  1328.  
  1329.       mparams.sched_priority = sched_get_priority_max(policy) - 1;
  1330.       sched_setscheduler(0, policy, &mparams);
  1331.  
  1332.       sparam1.sched_priority = sched_get_priority_max(policy);
  1333.       sparam2.sched_priority = sched_get_priority_max(policy);
  1334.  
  1335.  
  1336.       sem_init( &tDone1, 0, 0);
  1337.       sem_init( &tDone2, 0, 0);        
  1338.  
  1339.  
  1340.       /* Set up threads with OTHER policy and maximum priority */
  1341.       pthread_attr_init( &attr1 );
  1342.       pthread_attr_setscope( &attr1, PTHREAD_SCOPE_SYSTEM);
  1343.       pthread_attr_setschedpolicy( &attr1, policy );
  1344.       pthread_attr_setdetachstate( &attr1, PTHREAD_CREATE_DETACHED);
  1345.       pthread_attr_setschedparam( &attr1, &sparam1 );
  1346.  
  1347.       pthread_attr_init( &attr2 );
  1348.       pthread_attr_setscope( &attr2, PTHREAD_SCOPE_SYSTEM);
  1349.       pthread_attr_setschedpolicy( &attr2, policy );
  1350.       pthread_attr_setdetachstate( &attr2, PTHREAD_CREATE_DETACHED);
  1351.       pthread_attr_setschedparam( &attr2, &sparam2 );
  1352.  
  1353.       set1.thread_sem = &tDone1;
  1354.       set2.thread_sem = &tDone2;
  1355.  
  1356.       pthread_create( &thread1, &attr1, gl_transform_vb_range_scheduler, &set1);
  1357.       pthread_create( &thread2, &attr2, gl_transform_vb_range_scheduler, &set2); 
  1358.       firsttime = 0;
  1359.  
  1360.     } /* end if */
  1361.  
  1362.  
  1363.     set1.ctx = ctx;
  1364.     set1.start = VB->Start;
  1365.     set1.count = VB->Start + (VB->Count-VB->Start)/2;
  1366.     set1.firstPartToDo = firstPartToDo;
  1367.  
  1368.  
  1369.     set2.ctx = ctx;
  1370.     set2.start = VB->Start + (VB->Count - VB->Start)/2;
  1371.     set2.count = VB->Count;
  1372.     set2.firstPartToDo = firstPartToDo;
  1373.     
  1374.     set1.tsync = set2.tsync = 0;
  1375.  
  1376.  
  1377.     /* Wake the vertex buffer processing threads */
  1378.     sem_post( &tDone1 );
  1379.     sem_post( &tDone2 );
  1380.     sched_yield();
  1381.  
  1382.  
  1383.     /* Spin until both are done */
  1384.     while( !set1.tsync && !set2.tsync);
  1385.  
  1386.  
  1387.   }
  1388.   else {
  1389.  
  1390.  
  1391.     gl_transform_vb_range( ctx, VB->Start, VB->Count,
  1392.              &VB->ClipOrMask, &VB->ClipAndMask,
  1393.              firstPartToDo );
  1394.  
  1395.   } /* end if */
  1396.  
  1397. #else
  1398.  
  1399.     gl_transform_vb_range( ctx, VB->Start, VB->Count,
  1400.              &VB->ClipOrMask, &VB->ClipAndMask,
  1401.              firstPartToDo );
  1402.  
  1403. #endif
  1404.  
  1405.   if (VB->ClipAndMask) {
  1406.     gl_reset_vb( ctx, allDone );
  1407.     return;
  1408.   }
  1409.  
  1410.  
  1411. #ifdef PROFILE
  1412.   ctx->VertexTime += gl_time() - t0;
  1413.   ctx->VertexCount += VB->Count - VB->Start;
  1414. #endif
  1415.  
  1416.   /*
  1417.    * Now we're ready to rasterize the Vertex Buffer!!!
  1418.    *
  1419.    * If the device driver can't rasterize the vertex buffer then we'll
  1420.    * do it ourselves.
  1421.    */
  1422.   if (!ctx->Driver.RenderVB || !(*ctx->Driver.RenderVB)(ctx,allDone)) {
  1423.     gl_render_vb( ctx, allDone );
  1424.   }
  1425. }
  1426.  
  1427.  
  1428. /*
  1429.  * When the Vertex Buffer is full, this function applies the modelview
  1430.  * matrix to transform vertices and normals from object coordinates to
  1431.  * eye coordinates.  Next, we'll call gl_transform_vb_part2()...
  1432.  * This function might not be called when using vertex arrays.
  1433.  */
  1434. void gl_transform_vb_part1( GLcontext *ctx, GLboolean allDone )
  1435. {
  1436.   gl_transform_vb( ctx, GL_TRUE, allDone );
  1437. }
  1438.  
  1439.  
  1440. /*
  1441.  * Part 2 of Vertex Buffer transformation:  compute lighting, clipflags,
  1442.  * fog, texture coords, etc.
  1443.  * Before this function is called the VB->Eye coordinates must have
  1444.  * already been computed.
  1445.  * Callers:  gl_transform_vb_part1(), glDrawArraysEXT()
  1446.  */
  1447. void gl_transform_vb_part2( GLcontext *ctx, GLboolean allDone )
  1448. {
  1449.   gl_transform_vb( ctx, GL_FALSE, allDone );
  1450. }
  1451.  
  1452.